import time
from random import randint


class UniqueIDGenerator:
    def __init__(self, datacenter_id, worker_id):
        self.last_timestamp = -1
        self.sequence = 0
        self.datacenter_id = datacenter_id
        self.worker_id = worker_id

    def next_id(self):
        timestamp = self.time_gen()
        if timestamp < self.last_timestamp:
            offset = self.last_timestamp - timestamp
            if offset > 5:
                raise RuntimeError(f"Clock moved backwards. Refusing to generate id for {offset} milliseconds")

            time.sleep(offset / 1000.0)
            timestamp = self.time_gen()
            if timestamp < self.last_timestamp:
                raise RuntimeError(f"Clock moved backwards. Refusing to generate id for {offset} milliseconds")

        if self.last_timestamp == timestamp:
            self.sequence = (self.sequence + 1) & 4095
            if self.sequence == 0:
                timestamp = self.til_next_millis(self.last_timestamp)
        else:
            self.sequence = randint(1, 2)

        self.last_timestamp = timestamp
        return (timestamp - 1288834974657) << 22 | self.datacenter_id << 17 | self.worker_id << 12 | self.sequence

    def time_gen(self):
        return int(time.time() * 1000)

    def til_next_millis(self, last_timestamp):
        timestamp = self.time_gen()
        while timestamp <= last_timestamp:
            timestamp = self.time_gen()
        return timestamp




class Snowflake:

    @staticmethod
    def generate():
        generator = UniqueIDGenerator(datacenter_id=1, worker_id=1)
        return generator.next_id()





